﻿//-------------------------------------------------------------------
//	Copyright (c) 2012  Zhirnov Andrey
//	This file is part of the "OGL-Tools" project.
//	See copyright notice in "ShaderSaver.h".
//-------------------------------------------------------------------
/*
*/

#pragma once

#include "ShaderSaver.h"

namespace gl
{
	namespace UXTypes
	{
		using namespace UX_STL::UXTypes;
	}
	using namespace UX_STL::winapi;	// for wgl


//-------------------------------------------------------------------
// MACRO

#	ifndef GLAPI
#		define GLAPI			extern
#	endif
	
# ifdef PLATFORM_WINDOWS
#	define CONST	const
#	define DECLARE_HANDLE(name)	struct name##__{int unused;}; typedef struct name##__ *name
# endif

#	undef  GL_CALL
#	define GL_CALL( _func )		Instance()->_func


// options
#	define SAVE_ALL_SHADERS
#	define SAVE_ALL_PROGRAMS
#	define DISABLE_SAVING_SHADERS
#	define SAVE_PROGRAM_WITH_SHADERS


//-------------------------------------------------------------------
// TYPES

	typedef unsigned int GLenum;
	typedef unsigned char GLboolean;
	typedef unsigned int GLbitfield;
	typedef signed char GLbyte;
	typedef short GLshort;
	typedef int GLint;
	typedef int GLsizei;
	typedef unsigned char GLubyte;
	typedef unsigned short GLushort;
	typedef unsigned int GLuint;
	typedef float GLfloat;
	typedef float GLclampf;
	typedef double GLdouble;
	typedef double GLclampd;
	typedef void GLvoid;
	

	typedef char GLchar;

	typedef ptrdiff_t GLintptr;
	typedef ptrdiff_t GLsizeiptr;

	typedef ptrdiff_t GLintptrARB;
	typedef ptrdiff_t GLsizeiptrARB;

	typedef char GLcharARB;
	typedef unsigned int GLhandleARB;

	typedef unsigned short GLhalfARB;

	typedef unsigned short GLhalfNV;

	typedef UXTypes::int64 GLint64EXT;
	typedef UXTypes::uint64 GLuint64EXT;

	typedef UXTypes::int64 GLint64;
	typedef UXTypes::uint64 GLuint64;
	typedef struct __GLsync *GLsync;

	struct _cl_context;
	struct _cl_event;

	typedef void (CALLBACK *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
	typedef void (CALLBACK *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
	typedef void (CALLBACK *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
	typedef GLintptr GLvdpauSurfaceNV;
	

#ifdef PLATFORM_WINDOWS

	typedef struct _POINTFLOAT {
		FLOAT   x;
		FLOAT   y;
	} POINTFLOAT, *PPOINTFLOAT;

	typedef struct _GLYPHMETRICSFLOAT {
		FLOAT       gmfBlackBoxX;
		FLOAT       gmfBlackBoxY;
		POINTFLOAT  gmfptGlyphOrigin;
		FLOAT       gmfCellIncX;
		FLOAT       gmfCellIncY;
	} GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
	
	DECLARE_HANDLE( HPBUFFERARB );
	DECLARE_HANDLE( HPBUFFEREXT );
	DECLARE_HANDLE( HVIDEOOUTPUTDEVICENV );
	DECLARE_HANDLE( HPVIDEODEV );
	DECLARE_HANDLE( HPGPUNV );
	DECLARE_HANDLE( HGPUNV );
	DECLARE_HANDLE( HVIDEOINPUTDEVICENV );

	typedef struct _GPU_DEVICE {
		DWORD  cb;
		CHAR   DeviceName[32];
		CHAR   DeviceString[128];
		DWORD  Flags;
		RECT   rcVirtualScreen;
	} GPU_DEVICE, *PGPU_DEVICE;

#else	// not PLATFORM_WINDOWS
	
	typedef struct __GLXcontextRec *GLXContext;
	typedef XID GLXPixmap;
	typedef XID GLXDrawable;
	/* GLX 1.3 and later */
	typedef struct __GLXFBConfigRec *GLXFBConfig;
	typedef XID GLXFBConfigID;
	typedef XID GLXContextID;
	typedef XID GLXWindow;
	typedef XID GLXPbuffer;
	
	typedef void (*__GLXextFuncPtr)(void);
	
	typedef struct {
		int event_type;		/* GLX_DAMAGED or GLX_SAVED */
		int draw_type;		/* GLX_WINDOW or GLX_PBUFFER */
		unsigned long serial;	/* # of last request processed by server */
		Bool send_event;		/* true if this came for SendEvent request */
		Display *display;		/* display the event was read from */
		GLXDrawable drawable;	/* XID of Drawable */
		unsigned int buffer_mask;	/* mask indicating which buffers are affected */
		unsigned int aux_buffer;	/* which aux buffer was affected */
		int x, y;
		int width, height;
		int count;			/* if nonzero, at least this many more */
	} GLXPbufferClobberEvent;

	typedef struct {
		int type;
		unsigned long serial;	/* # of last request processed by server */
		Bool send_event;		/* true if this came from a SendEvent request */
		Display *display;		/* Display the event was read from */
		GLXDrawable drawable;	/* drawable on which event was requested in event mask */
		int event_type;
		int64_t ust;
		int64_t msc;
		int64_t sbc;
	} GLXBufferSwapComplete;

	typedef union __GLXEvent {
		GLXPbufferClobberEvent glxpbufferclobber;
		GLXBufferSwapComplete glxbufferswapcomplete;
		long pad[24];
	} GLXEvent;

#endif	// PLATFORM_WINDOWS


//-------------------------------------------------------------------
// ENUMS

#	include "gl_enum.h"

	

	
//-------------------------------------------------------------------
// HOOK FUNCTIONS

	
extern "C"
{	

#ifdef PLATFORM_WINDOWS
	GLAPI HGLRC CALLBACK wglCreateContextHook (HDC dc);
	GLAPI BOOL  CALLBACK wglDeleteContextHook (HGLRC rc);
	GLAPI PROC  CALLBACK wglGetProcAddressHook (LPCSTR lpszProc);
	GLAPI HGLRC CALLBACK wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList);

#else	// not PLATFORM_WINDOWS
	extern GLXContext glXCreateContextHook ( Display *dpy, XVisualInfo *vis,
					    GLXContext shareList, Bool direct );
	
	extern void glXDestroyContextHook ( Display *dpy, GLXContext ctx );

	extern __GLXextFuncPtr glXGetProcAddressARBHook (const GLubyte *);

	extern GLXContext glXCreateContextAttribsARB (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);

#endif	// PLATFORM_WINDOWS

	GLAPI void  CALLBACK glProgramStringARB (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
	GLAPI void  CALLBACK glShaderSource (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
	GLAPI void  CALLBACK glShaderSourceARB (GLhandleARB shader, GLsizei count, const GLcharARB ** string, const GLint *length);
	
	GLAPI void  CALLBACK glLinkProgram (GLuint program);
	GLAPI void  CALLBACK glLinkProgramARB (GLhandleARB programObj);
}


	
//-------------------------------------------------------------------
// FUNCTIONS

#	include "gl_func.h"

	
// typedefs //
#	undef  GL_BUILDFUNC
#	define GL_BUILDFUNC( _ret, _func, _in_params, _out_params, _hook, _switch ) \
		typedef _ret (CALLBACK * PFN##_func##PROC) (_in_params);

	GL_FUNCTIONS
	GLEXT_FUNCTIONS
		
#ifdef PLATFORM_WINDOWS
	WGL_FUNCTIONS
	WGLEXT_FUNCTIONS
#else
	GLX_FUNCTIONS
	GLXEXT_FUNCTIONS
#endif

	
extern "C"
{	

// forward declaration //
#	undef  GL_BUILDFUNC
#	define GL_BUILDFUNC( _ret, _func, _in_params, _out_params, _hook, _switch ) \
		GLAPI _ret CALLBACK _func (_in_params);
	
	GL_FUNCTIONS

#ifdef PLATFORM_WINDOWS
	WGL_FUNCTIONS
#else
	GLX_FUNCTIONS
#endif

	//GLEXT_FUNCTIONS
	//WGLEXT_FUNCTIONS

}
	

// variables //
#	undef  GL_BUILDFUNC
#	define GL_BUILDFUNC( _ret, _func, _in_params, _out_params, _hook, _switch ) \
		GLFuncPtr< PFN##_func##PROC >		_func;

	
	template <typename T>
	struct GLFuncPtr
	{
		T	_func;

		GLFuncPtr(): _func(nullptr) {}
		GLFuncPtr(T p): _func(p) {}

		T operator () () const	{ CHECK_VALUE_R( _func != nullptr, nullptr );  return _func; }
	};


	//
	// OpenGL Source Functions
	//

	struct GLSrcFunctions
	{
		GL_FUNCTIONS
		GLEXT_FUNCTIONS
		
#	ifdef PLATFORM_WINDOWS
		WGL_FUNCTIONS
		WGLEXT_FUNCTIONS
#	else
		GLX_FUNCTIONS
		GLXEXT_FUNCTIONS
#	endif
		

		GLSrcFunctions();
		~GLSrcFunctions();

		static void Create(void *pInstance = nullptr);
		static void Release();

#	ifdef PLATFORM_WINDOWS
		static HGLRC CreateInstance(HDC hDC);
		static HGLRC CreateInstanceExt(HDC hDC, HGLRC hSharedRC, const int *attribs);
#	else
		static GLXContext CreateInstance(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
		static GLXContext CreateInstanceExt(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
#	endif

		static void ReleaseInstance(void *pRC);

		static void SaveShader(GLenum type, GLuint id, GLsizei count, const GLchar* const *string, const GLint *length);
		static void SaveProgram(GLuint id, GLsizei count, const GLenum * shadertypes, const GLuint *shaders);
		static void SaveFullProgram(GLuint id, GLsizei count, const GLenum * shadertypes, const GLuint *shaders, const UXTypes::string *sources);
		static void SaveASMProgram(GLenum type, GLuint id, GLsizei len, const GLvoid *string);
		
		UX_STL::UXTypesExt::TLibrary		_sOpenGL;
		UX_STL::UXTypesExt::TLibrary		_sInteceptorLib;
		UX_STL::UXFileSystem::IFilePtr		_pSLPrograms;
		UX_STL::UXFileSystem::IFileSystem *	_pFS;
		UX_STL::UXLogger::ILogger *			_pLog;
		void *								_pInstance;
		int									_iNumContexts;
		UXTypes::string						_sOutputDir;
	};

	
#	undef  GL_BUILDFUNC
#	undef  CONST
#	undef  DECLARE_HANDLE

}	// gl
